package net.asfun.jvalog.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import net.asfun.jvalog.common.JdoerFactory;
import net.asfun.jvalog.entity.Label;
import net.asfun.jvalog.entity.Paper;
import net.asfun.jvalog.entity.Phase;
import net.asfun.jvalog.entity.Relation;
import net.asfun.jvalog.entity.Sort;
import net.asfun.jvalog.resource.LabelDao;
import net.asfun.jvalog.resource.MessageDao;
import net.asfun.jvalog.resource.MeterDao;
import net.asfun.jvalog.resource.PaperDao;
import net.asfun.jvalog.resource.PhaseDao;
import net.asfun.jvalog.util.Bridge;
import net.asfun.jvalog.util.Unifier;
import net.asfun.jvalog.util.UpdateManager;
import net.asfun.jvalog.util.ValueFormater;
import net.asfun.jvalog.vo.Pager;
import net.asfun.jvalog.vo.Post;


import com.google.appengine.api.datastore.Key;

public class PostService {


	public static Post getByUri(String uri) {
		Paper paper = PaperDao.getByUri(uri);
		return new Post(paper);
	}

	public static List<Post> listPublished(Pager pager) {
		List<Post> posts = new ArrayList<Post>();
		for(Paper paper : PaperDao.listPublished(Paper.POST_TYPE, pager) ) {
			posts.add(new Post(paper));
		}
		return posts;
	}

	public static List<Post> listRecent(int rssSize) {
		List<Post> posts = new ArrayList<Post>();
		for(Paper paper : PaperDao.listPublished(Paper.POST_TYPE, rssSize) ) {
			posts.add(new Post(paper));
		}
		return posts;
	}

	public static List<Post> listArchive(Pager pager, String... ymd) {
		String from=null, to=null;
		int numb=0;
		switch(ymd.length) {
		case 3 :
			numb = Integer.valueOf(ymd[2]);
			from = ymd[0] + "-" + ymd[1] + "-" + numb;
			to = ymd[0] + "-" + ymd[1] + "-" + (numb+1);
			break;
		case 2 :
			numb = Integer.valueOf(ymd[1]);
			from = ymd[0] + "-" + numb + "-01";
			to = ymd[0] + "-" + (numb+1) + "-01";
			break;
		case 1 :
			numb = Integer.valueOf(ymd[0]);
			from = numb + "-01-01";
			to = (numb+1) + "-01-01";
			break;	
		}
		Date afrom = ValueFormater.string2date(from, "yyyy-MM-dd");
		Date ato = ValueFormater.string2date(to, "yyyy-MM-dd");
		
		List<Post> posts = new ArrayList<Post>();
		for(Paper paper : PaperDao.listPublished(Paper.POST_TYPE, pager, afrom, ato) ) {
			posts.add(new Post(paper));
		}
		return posts;
	}

	public static List<Post> listAll(Pager pager) {
		List<Post> posts = new ArrayList<Post>();
		for( Paper paper : PaperDao.listAll(Paper.POST_TYPE, pager) ) {
			posts.add(new Post(paper));
		}
		return posts;
	}

	public static void addPost(Paper paper, String tagnames, Long[] categoryIds) {
		String uri = generateURI(paper.getDate(), paper.getSlogan());
		paper.setUri(uniqueURI(uri));
		JdoerFactory.jdoPaper.save(paper);
		
		if ( paper.isPublished() ) {
			Phase phase = PhaseDao.getByDate(paper.getDate());
			phase.setCount(phase.getCount() + 1);
		}
		
		Unifier.setUnique(paper.getKey(), "uri", paper.getUri());
		for (Relation tag : getTags(tagnames)) {
			tag.setLeft(paper.getKey());
			JdoerFactory.jdoRelation.save(tag);
		}
		for (Relation cat : getCategories(categoryIds)) {
			cat.setLeft(paper.getKey());
			JdoerFactory.jdoRelation.save(cat);
		}
		if ( paper.isPublished() ) {
			UpdateManager.enableCounterTask();
		}
	}

	
	private static String generateURI(Date date, String slogan) {
		StringBuffer buff = new StringBuffer();
		buff.append(ValueFormater.date2string(date, "yyyy/MM/dd/"))
			.append(slogan);
		return buff.toString();
	}
	
	private static String uniqueURI(String uri) {
		if ( ! Unifier.isUnique("Paper", "uri", uri) ) {
			uri += "~1";
			return uri = uniqueURI(uri);
		}
		return uri;
	}
	
	private static String uniqueURI(String uri, Key key) {
		if ( ! Unifier.isUnique(key, "uri", uri) ) {
			uri += "~1";
			return uri = uniqueURI(uri, key);
		}
		return uri;
	}
	
	private static List<Relation> getTags(String tagnames) {
		List<Relation> tags = new ArrayList<Relation>();
		String[] tagns = tagnames.split(",");
		for(String tag : tagns) {
			Label label = LabelDao.getOrSaveByName(tag);
			Relation rel = new Relation();
			rel.setRight(label.getKey());
			rel.setType(Bridge.POST_TAG);
			tags.add(rel);
		}
		return tags;
	}
	
	private static List<Relation> getCategories(Long[] categoryIds) {
		List<Relation> categories = new ArrayList<Relation>();
		for(Long id : categoryIds) {
			Sort sort = JdoerFactory.jdoSort.load(id);
			Relation rel = new Relation();
			rel.setRight(sort.getKey());
			rel.setType("post_category");
			categories.add(rel);
		}
		return categories;
	}

	public static void delete(Long id) {
		Paper paper = JdoerFactory.jdoPaper.load(id);
		if ( paper != null ) {
			if ( paper.getDate() != null ) {
				Phase pha = PhaseDao.getByDate(paper.getDate());
				pha.setCount(pha.getCount()-1);
			}
			
			Unifier.unsetUnique(paper.getKey(), "uri");
			JdoerFactory.jdoRelation.delete(Bridge.getRelationsByLeft(paper.getKey(), Bridge.POST_CATEGORY));
			JdoerFactory.jdoRelation.delete(Bridge.getRelationsByLeft(paper.getKey(), Bridge.POST_TAG));
			JdoerFactory.jdoMessage.delete(MessageDao.listAll(paper.getKey()));
			MeterDao.getCount(paper.getKey());
			if ( paper.isPublished() ) {
				UpdateManager.enableCounterTask();
			}
			JdoerFactory.jdoPaper.delete(paper);
		}
	}

	public static void update(Paper paper, String tagnames, Long[] categoryIds) {
		Paper record = JdoerFactory.jdoPaper.load(paper.getKey().getId());
		boolean isPublished = record.isPublished();
		Date oldDate = record.getDate();
		
		if ( paper.getTitle() != null )
			record.setTitle(paper.getTitle());
		if ( paper.getExcerpt() != null )
			record.setExcerpt(paper.getExcerpt());
		record.setPublished(paper.isPublished());
		if ( paper.getSlogan() != null )
			record.setSlogan(paper.getSlogan());
		if ( paper.getSource() != null )
			record.setSource(paper.getSource());
		if ( paper.getContent() != null )
			record.setContent(paper.getContent());
		if ( paper.getDate() != null )
			record.setDate(paper.getDate());
		
		String uri = generateURI(record.getDate(), record.getSlogan());
		record.setUri(uniqueURI(uri, record.getKey()));
		
		if ( record.isPublished() && isPublished ) {
			if ( ! ValueFormater.date2string(oldDate, "yyyyMM").equals(
					ValueFormater.date2string(record.getDate(), "yyyyMM"))) {
				Phase phase1 = PhaseDao.getByDate(record.getDate());
				phase1.setCount(phase1.getCount() + 1);
				Phase phase2 = PhaseDao.getByDate(oldDate);
				phase2.setCount(phase2.getCount() - 1);
			}
		}
		if ( record.isPublished() && !isPublished ) {
			Phase phase1 = PhaseDao.getByDate(record.getDate());
			phase1.setCount(phase1.getCount() + 1);
		}
		if ( !record.isPublished() && isPublished ) {
			Phase phase2 = PhaseDao.getByDate(oldDate);
			phase2.setCount(phase2.getCount() - 1);
		}
		
		Unifier.setUnique(record.getKey(), "uri", record.getUri());
		
		JdoerFactory.jdoRelation.delete(Bridge.getRelationsByLeft(record.getKey(), Bridge.POST_TAG));
		JdoerFactory.jdoRelation.delete(Bridge.getRelationsByLeft(record.getKey(), Bridge.POST_CATEGORY));
		
		for (Relation tag : getTags(tagnames)) {
			tag.setLeft(record.getKey());
			JdoerFactory.jdoRelation.save(tag);
		}
		for (Relation cat : getCategories(categoryIds)) {
			cat.setLeft(record.getKey());
			JdoerFactory.jdoRelation.save(cat);
		}
		if ( isPublished && ! record.isPublished()
				|| !isPublished && record.isPublished() ) {
			UpdateManager.enableCounterTask();
		}
		if ( isPublished && record.isPublished() ) {
			UpdateManager.enableCacheTask();
		}
	}

	public static Post getById(Long id) {
		return new Post(JdoerFactory.jdoPaper.load(id));
	}
}
